/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mrroman.linksender.gui;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.ResourceBundle;
import java.util.logging.Logger;

import com.mrroman.linksender.ioc.Init;
import com.mrroman.linksender.ioc.Locales;
import com.mrroman.linksender.ioc.Log;
import com.mrroman.linksender.ioc.Name;
import com.mrroman.linksender.sender.Message;
import com.mrroman.linksender.sender.MessageEvent;
import com.mrroman.linksender.sender.MessageListener;
import com.mrroman.linksender.sender.Pinger;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.LinkedList;
import java.util.Map.Entry;

/**
 *
 * @author gorladam
 */
@Name("sender.PingLister")
public class PingListener implements MessageListener {

    @Log
    private Logger logger;
    @Locales
    private ResourceBundle messages;
    private final HashMap<String, Object[]> ziomy = new HashMap<String, Object[]>();
    private long lastFiltered;
    public static final String EVENT_NEWUSER = "EVENT_NEWUSER";
    public static final String EVENT_USEROUT = "EVENT_USEROUT";

    @Init
    public void init() {
        lastFiltered = System.currentTimeMillis();
    }

    @Override
    public void messageSend(MessageEvent event) {
        Message message = event.getMessage();
        if ((message.getFlags() & Message.MESSAGE_FLAG_SELF) > 0) {
            return;
        }
        if ((message.getFlags() & Message.MESSAGE_FLAG_HIDDEN) > 0) {
            if (Pinger.PONGMESSAGE.equals(message.getMessage())) {
                synchronized (ziomy) {
                    logger.finest(messages.getString("message_recieved") + " " + message);
                    boolean foundNew = ziomy.get(message.getSender()) == null;
                    ziomy.put(message.getSender(),
                            new Object[]{
                                new Long(System.currentTimeMillis()),
                                message.getAddressOfSender()
                            });
                    if (foundNew) {
                        logger.fine(message.getSender() + " is online");
                        propertyChangeSupport.firePropertyChange(EVENT_NEWUSER, null, message.getSender());
                    }
                }
                filterInactiveUsers();
            }
        }
    }

    private void filterInactiveUsers() {
        double delta = 0.001 * (System.currentTimeMillis() - lastFiltered);
        logger.finest("Last filtered " + delta + " sec ago");
        if (delta > 5) {
            synchronized (ziomy) {
                lastFiltered = System.currentTimeMillis();
                LinkedList<String> absentList = new LinkedList<String>();
                for (String guy : ziomy.keySet()) {
                    Long lastVisible = (Long) ziomy.get(guy)[0];
                    delta = 0.001 * (lastFiltered - lastVisible);
                    logger.finest(guy + " last visible " + delta + " sec ago");
                    if (delta > 15) {
                        absentList.add(guy);
                    }
                }
                for (String guy : absentList) {
                    logger.fine(guy + " is offline");
                    ziomy.remove(guy);
                    propertyChangeSupport.firePropertyChange(EVENT_USEROUT, guy, null);
                }
            }
        }
    }

    public ArrayList<String> getActiveUsers() {
        synchronized (ziomy) {
            filterInactiveUsers();
            ArrayList<String> list = new ArrayList<String>(ziomy.size());
            for (String guy : ziomy.keySet()) {
                list.add(guy);
            }
            return list;
        }
    }

    public int size() {
        filterInactiveUsers();
        return ziomy.size();
    }

    public InetAddress getAddressOfUser(String nick) {
        synchronized (ziomy) {
            Object[] o = ziomy.get(nick);
            if (o == null) {
                return null;
            }
            return (InetAddress) o[1];
        }
    }

    public String getNickOfUser(InetAddress ip) {
        if (ip == null) {
            return null;
        }
        synchronized (ziomy) {
            for (Entry<String, Object[]> k : ziomy.entrySet()) {
                InetAddress k_ip = (InetAddress) k.getValue()[1];
                if (ip.equals(k_ip)) {
                    return k.getKey();
                }
            }
        }
        return ip.toString();
    }

    @Override
    public void serverInfo(MessageEvent event) {
    }
    private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

    /**
     * Add PropertyChangeListener.
     *
     * @param listener
     */
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        propertyChangeSupport.addPropertyChangeListener(listener);
    }

    /**
     * Remove PropertyChangeListener.
     *
     * @param listener
     */
    public void removePropertyChangeListener(PropertyChangeListener listener) {
        propertyChangeSupport.removePropertyChangeListener(listener);
    }
}
